shiny game in browser:tic tac toe
create shiny in quarto doc
1 step 1 add quarto extension in project root folder
#| eval: false
quarto add quarto-ext/shinylive
2 step 2 add in header
---
filters:
- shinylive
---
3 step 3 make shiny app
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| viewerHeight: 600
#| components: [editor, viewer]
library(shiny)
# UI
ui <- fluidPage(
titlePanel("Tic-Tac-Toe"),
sidebarLayout(
sidebarPanel(
actionButton("new_game", "New Game"),
h4("Current Player:"),
textOutput("current_player")
),
mainPanel(
uiOutput("board"),
h3(textOutput("game_status"))
)
)
)
# Server
server <- function(input, output, session) {
# Game state
game <- reactiveValues(
board = matrix(rep("", 3), nrow = 3, ncol = 3),
current_player = "X",
game_over = FALSE,
winner = NULL
)
# Render the game board
output$board <- renderUI({
fluidRow(
lapply(1:3, function(i) {
column(4,
lapply(1:3, function(j) {
actionButton(paste0("cell_", i, "_", j), label = game$board[i, j], style = "width:100px; height:100px; font-size: 40px;")
})
)
})
)
})
# Display current player
output$current_player <- renderText({
game$current_player
})
# Handle cell clicks
observe({
lapply(1:3, function(i) {
lapply(1:3, function(j) {
observeEvent(input[[paste0("cell_", i, "_", j)]], {
if (game$board[i, j] == "" && !game$game_over) {
game$board[i, j] <- game$current_player
check_winner()
if (!game$game_over) {
game$current_player <- ifelse(game$current_player == "X", "O", "X")
}
}
})
})
})
})
# Check for a winner
check_winner <- function() {
board <- game$board
# Check rows
for (i in 1:3) {
if (all(board[i, ] == game$current_player) && board[i, 1] != "") {
game$winner <- game$current_player
game$game_over <- TRUE
return()
}
}
# Check columns
for (j in 1:3) {
if (all(board[, j] == game$current_player) && board[1, j] != "") {
game$winner <- game$current_player
game$game_over <- TRUE
return()
}
}
# Check diagonals
if (all(diag(board) == game$current_player) && board[1, 1] != "") {
game$winner <- game$current_player
game$game_over <- TRUE
return()
}
if (all(diag(board[ , 3:1]) == game$current_player) && board[1, 3] != "") {
game$winner <- game$current_player
game$game_over <- TRUE
return()
}
# Check for a tie
if (all(board != "")) {
game$winner <- "Tie"
game$game_over <- TRUE
}
}
# Display game status
output$game_status <- renderText({
if (game$game_over) {
if (game$winner == "Tie") {
"It's a tie!"
} else {
paste("Player", game$winner, "wins!")
}
}
})
# New game button
observeEvent(input$new_game, {
game$board <- matrix(rep("", 3), nrow = 3, ncol = 3)
game$current_player <- "X"
game$game_over <- FALSE
game$winner <- NULL
})
}
# Run the application
shinyApp(ui = ui, server = server)